import 'dart:io';

import 'package:flutter/material.dart';
import 'package:upgrade/net/dio_client.dart';
import 'package:upgrade/upgrade_dialog_widget.dart';
import 'package:upgrade/upgrade_manager_option.dart';

import 'base_bean.dart';
import 'custom_exception.dart';
import 'log_util.dart';
import 'upgrade_platform_interface.dart';

class UpgradeManager {
  UpgradeManager._internal();

  factory UpgradeManager.instance() => _instance;

  static final UpgradeManager _instance = UpgradeManager._internal();

  UpgradeManagerOption option = UpgradeManagerOption();
  var versionCode = 0;
  var versionName = "";

  final String TAG = "UpgradeManager";
  static const String DEFAULT_HOST = "192.168.31.67:8080";
  static const String DEFAULT_DOWNLOAD_HOST = "192.168.31.67:8080";

  Future<String?> getPlatformVersion() {
    return UpgradePlatform.instance.getPlatformVersion();
  }

  Future init({UpgradeManagerOption? option}) {
    this.option.host = option?.host ?? DEFAULT_HOST;
    this.option.downloadHost = option?.downloadHost ?? DEFAULT_DOWNLOAD_HOST;
    LogUtil.printLog = option?.printLog ?? false;
    this.option.appKey = option?.appKey;
    return UpgradePlatform.instance.getVersionInfo().then((value) {
      if (value != null) {
        LogUtil.i(TAG, value);
        versionName = value["versionName"] as String;
        versionCode = int.parse("${value["versionCode"]}");
      }
    });
  }

  setOption(UpgradeManagerOption option) {
    this.option = option;
  }

  setOptions({String? host, String? downloadHost, String? appKey, bool? printLog}) {
    option.host = host;
    option.downloadHost = downloadHost;
    LogUtil.printLog = printLog ?? false;
    option.appKey = appKey;
  }

  UpgradeOptionBuilder optionBuilder(BuildContext context) {
    return UpgradeOptionBuilder(option, context);
  }

  String _getPlatForm(){
    if(Platform.isAndroid){
      return "android";
    }else if(Platform.isIOS){
      return "ios";
    }else if(Platform.isFuchsia){
      return "fuchsia";
    }else if(Platform.isLinux){
      return "linux";
    }else if(Platform.isMacOS){
      return "macos";
    }else if(Platform.isWindows){
      return "windows";
    }
    return Platform.operatingSystem;
  }

  /// 手动检查更新
  /// @param doOnSuccess 请求成功
  /// @param doOnError 请求失败
  checkUpgrade(Function(BaseBean data) doOnSuccess, Function(CustomException e)? doOnError) {
    if (option.appKey == null) {
      doOnError?.call(CustomException.notInitException);
      return;
    }

    var url = "${option.host}/distribute/app/checkUpgrade";

    var params = {};
    params["appKey"] = option.appKey;
    params["versionCode"] = versionCode;
    params["versionName"] = versionName;
    params["platform"] = _getPlatForm();
    LogUtil.i(TAG, url);
    LogUtil.i(TAG, params);

    dioClient.request(url, data: params).then((response) {
      var code = response.statusCode;
      if (response.statusCode == 200) {
        LogUtil.i(TAG, response.data.toString());
        BaseBean baseBean = BaseBean.fromJson(response.data);
        if (baseBean.isSuccess()) {
          doOnSuccess.call(baseBean);
        } else {
          doOnError?.call(CustomException.interfaceException(baseBean.code, baseBean.msg));
        }
      } else {
        doOnError?.call(CustomException.httpCodeErrorException(code));
      }
    }).onError((error, stackTrace) {
      LogUtil.i(TAG, error.toString());
      LogUtil.i(TAG, stackTrace.toString());
      doOnError?.call(CustomException.netException(Exception(error.toString())));
    });
  }
}

class UpgradeInterface {
  UpgradeOptionBuilder optionBuilder;
  BuildContext? context;

  UpgradeInterface(
    this.context,
    this.optionBuilder,
  );

  /// 检查更新，手动处理异常情况
  checkUpgrade(Function(CustomException e)? doOnError, Function()? noNewVersion) {
    if (context == null) {
      doOnError?.call(CustomException.nullContextException);
      return;
    }
    UpgradeManager.instance().checkUpgrade((BaseBean baseBean) {
      var versionList = baseBean.data;
      if (versionList == null || versionList.isEmpty) {
        noNewVersion?.call();
        return;
      }
      var errorType = 2004;

      bool contextAvailable = false;

      if (context != null) {
        if (context?.mounted == true) {
          contextAvailable = true;
        } else {
          errorType = 2003;
          contextAvailable = false;
        }
      } else {
        errorType = 2004;
        contextAvailable = false;
      }

      if (contextAvailable) {
        optionBuilder.doOnError = doOnError;
        showDialog(
            context: context!,
            barrierDismissible: false,
            builder: (buildContext) {
              return WillPopScope(
                  onWillPop: () {
                    return Future.value(false);
                  },
                  child: UnconstrainedBox(child: UpgradeDialog(versionList, optionBuilder)));
            });
      } else {
        switch (errorType) {
          case 2002:
            doOnError?.call(CustomException.nullContextException);
            break;
          case 2003:
            doOnError?.call(CustomException.appContextException);
            break;
          case 2004:
            doOnError?.call(CustomException.activityDestroyException);
            break;
        }
      }
    }, doOnError);
  }
}

class UpgradeOptionBuilder {
  UpgradeManagerOption option;
  BuildContext? context;
  var isShowHistoryVersion = false;
  var allowDownloadHistoryVersion = false;

  Function(
    bool isForce,
  )? cancelUpgradeListener;
  Function(
    int progress,
  )? downloadProgressUpdateListener;
  Function(
    String path,
  )? downloadFinishListener;
  Function(
    CustomException exception,
  )? doOnError;

  UpgradeOptionBuilder(this.option, this.context);

  /// 是否显示历史版本
  UpgradeOptionBuilder showHistoryVersion(bool showHistoryVersion) {
    isShowHistoryVersion = showHistoryVersion;
    return this;
  }

  /// 下载完成
  UpgradeOptionBuilder doOnDownloadFinish(Function(String path) doOnDownloadFinish) {
    downloadFinishListener = doOnDownloadFinish;
    return this;
  }

  /// 下载进度
  UpgradeOptionBuilder doOnDownloadProgressUpdate(
      Function(int progress) doOnDownloadProgressUpdate) {
    downloadProgressUpdateListener = doOnDownloadProgressUpdate;
    return this;
  }

  /// 下载地址
  UpgradeOptionBuilder downloadHost(String downloadHost) {
    option.downloadHost = downloadHost;
    return this;
  }

  /// 取消更新后的操作

  UpgradeOptionBuilder doOnCancelUpgrade(Function(bool isForce) doOnCancelUpgrade) {
    cancelUpgradeListener = doOnCancelUpgrade;
    return this;
  }

  /// 是否可以下载历史版本
  UpgradeOptionBuilder isAllowDownloadHistoryVersion(bool allowDownloadHistoryVersion) {
    this.allowDownloadHistoryVersion = allowDownloadHistoryVersion;
    return this;
  }

  UpgradeInterface build() {
    return UpgradeInterface(context, this);
  }
}
